﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Ue.Extensions;

namespace Ue.Tests.Extensions
{
    /// <summary>
    /// IConvertibleExtensions 的摘要说明
    /// </summary>
    [TestClass]
    public class IConvertibleExtensionTests
    {
        #region As

        [TestMethod]
        public void AsErrorReturnDefaultValue()
        {
            string number = "fa";

            Assert.AreEqual(999, number.As<int>(999));
            Assert.IsTrue(number.As<bool>(true));

            DateTime now = DateTime.Now;
            Assert.AreEqual(now, number.As<DateTime>(now));
        }

        [TestMethod]
        public void StringAsInt()
        {
            string number = "98";

            Assert.AreEqual<int>(98, number.As<int>());
        }

        [TestMethod]
        public void SelfIsNullReturnDefault()
        {
            object obj = null;

            Assert.AreEqual(0, obj.As<int>());
        }

        [TestMethod]
        public void StringAsEnum()
        {
            FakeEnum fakeEnum = FakeEnum.Item2;

            Assert.AreEqual(fakeEnum, "Item2".As<FakeEnum>());
        }

        [TestMethod]
        public void IntAsEnum()
        {
            int fakeEnum = (int)FakeEnum.Item2;

            Assert.AreEqual(FakeEnum.Item2, fakeEnum.As<FakeEnum>());
        }

        [TestMethod]
        public void NumberStringAsEnum()
        {
            string itemNumberString = ((int)FakeEnum.Item2).ToString();

            Assert.AreEqual(FakeEnum.Item2, itemNumberString.As<FakeEnum>());
        }

        [TestMethod]
        public void StringAsBoolean()
        {
            string booleanStr = "FALSE";

            Assert.IsFalse(booleanStr.As<bool>());

            booleanStr = "0";
            Assert.IsFalse(booleanStr.As<bool>());
        }

        [TestMethod]
        public void AsNullable()
        {
            object number = "1";
            Assert.AreEqual(1, number.As<int?>());

            number = null;
            Assert.AreEqual(null, number.As<int?>());
        }
        [TestMethod]
        public void EmptyStringAsNullable()
        {
            Assert.AreEqual(null, string.Empty.As<int?>());
        }

        [TestMethod]
        public void DBNullAsOjbect()
        {
            object obj = DBNull.Value;

            Assert.IsNull(obj.As<object>());
        }

        [TestMethod]
        public void SubClassAsAbstractClass()
        {
            FakeClass fakeClass = new FakeClass();

            Assert.AreEqual(fakeClass, (FakeAbstractClass)fakeClass);

            Assert.AreEqual(fakeClass, fakeClass.As<FakeAbstractClass>());
        }

        [TestMethod]
        public void SubClassAsInterface()
        {
            FakeClass fakeClass = new FakeClass();

            Assert.AreEqual(fakeClass, (FakeInterface)fakeClass);

            Assert.AreEqual(fakeClass, fakeClass.As<FakeInterface>());
        }

        [TestMethod]
        public void AsSelf()
        {
            FakeClass fakeClass = new FakeClass();

            Assert.AreEqual(fakeClass, fakeClass.As<FakeClass>());
        }

        [TestMethod]
        public void AsGuid()
        {
            string guidString = Guid.NewGuid().ToString();

            Assert.AreEqual(new Guid(guidString), guidString.As<Guid>());
        }
        [TestMethod]
        public void GuidAsString()
        {
            Guid guid = Guid.NewGuid();

            Assert.AreEqual(guid.ToString(), guid.As<string>());
        }

        [TestMethod]
        public void AsUri()
        {
            string url = "http://www.sina.com.cn";
            Uri uri = new Uri(url);

            Assert.AreEqual(uri, url.As<Uri>());
        }

        [TestMethod]
        public void AsTimeSpan()
        {
            TimeSpan span = new TimeSpan(100);

            Assert.AreEqual(span, span.ToString().As<TimeSpan>());
        }

        [TestMethod]
        public void AsDateTime()
        {
            DateTime dateTime = DateTime.Now;

            Assert.AreEqual(dateTime.ToString(), dateTime.ToString().As<DateTime>().ToString());
        }

        [TestMethod]
        public void AsDataTimeOffset()
        {
            DateTimeOffset offset = DateTimeOffset.Now;

            Assert.AreEqual(offset.ToString(), offset.ToString().As<DateTimeOffset>().ToString());
        }

        [TestMethod]
        public void AsDateTimeByNumber()
        {
            Assert.AreEqual(new DateTime(2011, 1, 1).ToString(), "2011".As<DateTime>().ToString());

            Assert.AreEqual(new DateTime(2011, 10, 1).ToString(), "201110".As<DateTime>().ToString());

            Assert.AreEqual(new DateTime(2011, 10, 11).ToString(), "20111011".As<DateTime>().ToString());
        }

        [TestMethod]
        public void FormatErrorReturnDefaultValue()
        {
            string str = "abc";

            Assert.AreEqual(0, str.As<int>());
        }

        [TestMethod]
        public void AsType()
        {
            object strType = typeof(string).FullName;

            Assert.AreEqual(strType, strType.As<Type>().FullName);
        }

        #endregion

        private enum FakeEnum
        {
            Item1 = 1,
            Item2 = 2,
            Item3 = 3
        }

        private abstract class FakeAbstractClass
        {

        }
        internal interface FakeInterface
        {
        }
        private class FakeClass : FakeAbstractClass, FakeInterface
        {
        }
    }
}
